package cn.shengchao.examstar.pay.model.service.fy;

import cn.shengchao.examstar.pay.model.service.fy.dto.Parameter;
import cn.shengchao.examstar.pay.model.service.fy.dto.ParameterCollection;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.util.List;

public class Utils {

    public static ParameterCollection paraFilter(ParameterCollection params) {
        if (params == null) {
            return new ParameterCollection();
        }
        return params.filterForSigning();
    }

    public static String createLinkString(ParameterCollection params) {
        if (params == null) {
            return "";
        }
        return params.createLinkString();
    }

    public static String getSign(ParameterCollection params, String insPrivateKey)
            throws InvalidKeySpecException, SignatureException, NoSuchAlgorithmException,
            InvalidKeyException, IOException {

        ParameterCollection paramsToSign = paraFilter(params);
        String preSignStr = createLinkString(paramsToSign);

        System.out.println(
                "==============================待签名字符串==============================\r\n" + preSignStr);

        String sign = Sign.sign(preSignStr, insPrivateKey);
        if (sign != null) {
            sign = sign.replace("\r\n", "").replace("\n", "");
        }

        System.out.println(
                "==============================签名字符串==============================\r\n" + sign);

        return sign;
    }

    public static Boolean verifySign(ParameterCollection params, String signFromServer, String fyPublicKey)
            throws Exception {

        ParameterCollection paramsToVerify = paraFilter(params);
        String preSignStr = createLinkString(paramsToVerify);

        System.out.println(
                "==============================待验签字符串 (verifySign)==============================\r\n" + preSignStr);
        System.out.println(
                "==============================服务器签名 (verifySign)==============================\r\n" + signFromServer);

        return Sign.verify(preSignStr.getBytes(Const.charset), fyPublicKey, signFromServer);
    }

    public static ParameterCollection xmlToParameterCollection(String xmlStr) throws DocumentException {
        ParameterCollection collection = new ParameterCollection();
        if (xmlStr == null || xmlStr.trim().isEmpty()) {
            return collection;
        }
        Document doc;
        try {
            doc = DocumentHelper.parseText(xmlStr);
            Element root = doc.getRootElement();
            @SuppressWarnings("unchecked") // dom4j uses raw types for elements()
            List<Element> children = root.elements();
            if (children != null && !children.isEmpty()) {
                for (Element child : children) {
                    collection.add(child.getName(), child.getStringValue().trim());
                }
            }
        } catch (DocumentException e) {
            System.err.println("Failed to parse XML string: " + xmlStr);
            throw e;
        }
        return collection;
    }

    public static void main(String[] args) {
        String xmlStr =
                "<?xml version=\"1.0\" encoding=\"GBK\" standalone=\"yes\"?>\n"
                        + "<xml>\n"
                        + "    <sign>1\n2 3   4:5</sign>\n"
                        + "    <field1>value1</field1>\n"
                        + "</xml>";
        try {
            ParameterCollection params = xmlToParameterCollection(xmlStr);
            for (Parameter p : params) {
                System.out.println("Parsed XML Param: " + p.getName() + " = " + p.getValue());
            }
            System.out.println("Sign from XML: " + params.getValue("sign"));
        } catch (DocumentException e) {
            e.printStackTrace();
        }
    }
}
